#include "Book.h"
#include <sstream>
#include "../Commons/Utils.h"
using namespace Entities;
using namespace Commons;

Book::Book() :
	IRecordable() {

	this->words = new vector<string> ();
	this->status = 0;
}

string Book::getTitle() {
	return this->title;
}

string Book::getPublisher() {
	return this->publisher;
}

string Book::getAuthor() {
	return this->author;
}

vector<string>* Book::getWords() {
	return this->words;
}

int Book::getStatus(){
    return this->status;
}

void Book::setTitle(string title) {
	this->title = title;
}

void Book::setPublisher(string publisher) {
	this->publisher = publisher;
}

void Book::setAuthor(string author) {
	this->author = author;
}

void Book::setStatus(int status){
	this->status = status;
}

void Book::addWord(string wordToAdd) {
	this-> words->push_back(wordToAdd);
}

//IRecordable methods

void Book::fillEntity(char *buffer, unsigned int bufferSize) {

	stringstream* ss = new stringstream(stringstream::in | stringstream::out | stringstream::binary);
	unsigned int status = 0;

	//write buffer into stringStream
	ss->seekg(0, ios::beg);
	ss->write(buffer, bufferSize);

	//fill status
	ss->read((char*) &status, sizeof(int));
	this->status = status;

	//fill title
	this->title = Utils::GetNextStringValue(ss);

	//fill author
	this->author = Utils::GetNextStringValue(ss);

	//fill publisher
	this->publisher = Utils::GetNextStringValue(ss);

	//fill words
	while(ss->tellg() < bufferSize){
		string currentWord = Utils::GetNextStringValue(ss);
		this->words->push_back(currentWord);
	}


	delete ss;
}

char* Book::buildBuffer() {

	stringstream* ss = new stringstream(stringstream::in | stringstream::out | stringstream::binary);
	int status = this->status;
	unsigned int titleSize = title.size();
	unsigned int authorSize = author.size();
	unsigned int publisherSize = publisher.size();
	unsigned int bufferSize = getBufferSize();
	char* buffer = new char[bufferSize];

	//add header
	ss->seekp(0, ios::end);
	ss->write((char*) &bufferSize, sizeof(int));
	ss->write((char*) &status, sizeof(int));

	//add records
	ss->write((char*) &titleSize, sizeof(int));
	ss->write(title.c_str(), title.size());
	ss->write((char*) &authorSize, sizeof(int));
	ss->write(author.c_str(), author.size());
	ss->write((char*) &publisherSize, sizeof(int));
	ss->write(publisher.c_str(), publisher.size());

	for (unsigned int i = 0; i < words->size(); i++){
		string currentWord = words->at(i);
		int currentWordSize = currentWord.size();

		ss->write((char*) &currentWordSize, sizeof(int));
		ss->write(currentWord.c_str(), currentWord.size());
	}

	//build buffer
	ss->read(buffer, bufferSize);

	return buffer;
}

unsigned int Book::getBufferSize() {

	unsigned int recordSize = 0;

	recordSize += sizeof(int); //size of bufferFullSize field
	recordSize += sizeof(int); //size of status field
	recordSize += sizeof(int) + title.size();
	recordSize += sizeof(int) + author.size();
	recordSize += sizeof(int) + publisher.size();

	//each word has two fields: wordSize (int) | word (varchar)
	for (unsigned int i = 0; i < words->size(); i++){
		recordSize += sizeof(int) + words->at(i).size();
	}

	return recordSize;
}

unsigned int Book::getEntityID() {
	return this->id;
}

void Book::setEntityID(unsigned int entityID) {
	this->id = entityID;
}

Book::~Book() {
	delete words;
}
